package com.evil.application.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evil.application.mapper.ApplicationApplySettingMapper;
import com.evil.application.mapper.ApplicationOrderMapper;
import com.evil.application.pojo.dto.apply.CopyAppApplySettingReqDTO;
import com.evil.application.pojo.dto.order.StatisticsOrderDTO;
import com.evil.application.pojo.entity.ApplicationApplySetting;
import com.evil.application.pojo.entity.ApplicationInfo;
import com.evil.application.service.ApplicationApplySettingService;
import com.evil.common.application.enums.ApplicationVersionEnum;
import com.evil.common.application.enums.order.OrderProcessStatusEnum;
import com.evil.common.core.enums.RCodeEnum;
import com.evil.common.core.enums.SwitchEnum;
import com.evil.common.core.exception.BusinessException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * 应用提交设置表
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
@Slf4j
@RestController
@AllArgsConstructor
public class ApplicationApplySettingServiceImpl extends ServiceImpl<ApplicationApplySettingMapper, ApplicationApplySetting> implements ApplicationApplySettingService {

    private final ApplicationOrderMapper applicationOrderMapper;

    private final ApplicationLogServiceImpl logService;

    /**
     * 检查应用申请配置
     *
     * @param applicationInfo applicationInfo
     */
    @Override
    public void checkApplicationApplySetting(ApplicationInfo applicationInfo) {
        Long applicationId = applicationInfo.getApplicationId();
        // 获取应用提交设置信息
        ApplicationApplySetting applySetting = this.baseMapper
                .findByIdAppIdAndVersion(applicationId, ApplicationVersionEnum.RELEASE_VERSION.getId());

        StatisticsOrderDTO statisticsOrderDTO = new StatisticsOrderDTO();
        statisticsOrderDTO.setApplicationId(applicationId);
        statisticsOrderDTO.setNotEqProcessStatus(OrderProcessStatusEnum.DRAFT_BOX.getId());

        boolean thanLimit = false;
        if (SwitchEnum.isOpen(applySetting.getApplyTotalLimitStatus()) && null != applySetting.getApplyTotalLimit()) {
            // 开启总提交限制
            thanLimit = applicationOrderMapper.countByOrderReqDTO(statisticsOrderDTO) >= applySetting.getApplyTotalLimit();
        }

        Date now = new Date();
        if (SwitchEnum.isOpen(applySetting.getApplyMonthLimitStatus()) && null != applySetting.getApplyMonthLimit()) {
            // 开启月提交限制
            statisticsOrderDTO.setBeginCreated(DateUtil.beginOfMonth(now));
            statisticsOrderDTO.setEndCreated(DateUtil.endOfMonth(now));
            thanLimit = applicationOrderMapper.countByOrderReqDTO(statisticsOrderDTO) >= applySetting.getApplyTotalLimit();
        }

        if (SwitchEnum.isOpen(applySetting.getApplyTimeLimitStatus())) {
            // 开启时间提交限制
            if (null != applySetting.getApplyLimitBeginTime()) {
                // 有开始时间
                thanLimit = now.after(applySetting.getApplyLimitBeginTime());
            }
            if (null != applySetting.getApplyLimitEndTime()) {
                // 有结束时间
                thanLimit = now.before(applySetting.getApplyLimitBeginTime());
            }
        }

        if (thanLimit) {
            throw new BusinessException(RCodeEnum.APPLICATION_APPLY_MORE_THAN_LIMIT);
        }
    }

    /**
     * 初始化应用提交设置
     *
     * @param applicationInfo applicationInfo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initApplySetting(ApplicationInfo applicationInfo) {
        // 先初始化设计版
        ApplicationApplySetting designApplySetting = this.baseMapper.isExistByAppIdAndVersion(
                applicationInfo.getApplicationId(), ApplicationVersionEnum.DESIGN_VERSION.getId())
                // 不存在得补
                .orElseGet(() -> this.createApplicationApplySetting(applicationInfo, ApplicationVersionEnum.DESIGN_VERSION));

        // 先初始化发布版
        ApplicationApplySetting releaseApplySetting = this.baseMapper.isExistByAppIdAndVersion(
                applicationInfo.getApplicationId(), ApplicationVersionEnum.RELEASE_VERSION.getId())
                // 不存在得补
                .orElseGet(() -> this.createApplicationApplySetting(applicationInfo, ApplicationVersionEnum.RELEASE_VERSION));

        // 然后发布 设计版 -> 发布版
        this.replaceApplicationApplySetting(designApplySetting, releaseApplySetting);
    }

    /**
     * 删除应用提交设置
     *
     * @param applicationInfo applicationInfo
     */
    @Override
    public void deleteApplySetting(ApplicationInfo applicationInfo) {
        ApplicationVersionEnum.forEach(em -> {
            ApplicationApplySetting applicationApplySetting = this.baseMapper.findByIdAppIdAndVersion(applicationInfo.getApplicationId(), em.getId());
            applicationApplySetting.setIsDeleted(SwitchEnum.YES.getId());

            logService.saveAndCheck(this.baseMapper, ApplicationApplySetting::getApplicationApplySettingId, applicationApplySetting);
        });
    }

    /**
     * 复制应用提交设置
     *
     * @param copyAppApplySettingReqDTO copyAppApplySettingReqDTO
     */
    @Override
    public void copyApplySetting(CopyAppApplySettingReqDTO copyAppApplySettingReqDTO) {
        ApplicationInfo source = copyAppApplySettingReqDTO.getSource();
        ApplicationInfo target = copyAppApplySettingReqDTO.getTarget();

        ApplicationVersionEnum.forEach(em -> {
            ApplicationApplySetting applicationApplySetting = this.baseMapper.findByIdAppIdAndVersion(source.getApplicationId(), em.getId());

            ApplicationApplySetting copyApplySetting = BeanUtil.copyProperties(applicationApplySetting, ApplicationApplySetting.class);
            copyApplySetting.setApplicationApplySettingId(null);
            copyApplySetting.setApplicationId(target.getApplicationId());

            logService.saveAndCheck(this.baseMapper, ApplicationApplySetting::getApplicationApplySettingId, copyApplySetting);
        });
    }

    /**
     * 发布应用提交设置
     *
     * @param applicationInfo applicationInfo
     */
    @Override
    public void publishApplySetting(ApplicationInfo applicationInfo) {
        this.replaceApplicationApplySetting(applicationInfo, true);
    }

    /**
     * 还原应用提交设置
     *
     * @param applicationInfo applicationInfo
     */
    @Override
    public void restoreApplySetting(ApplicationInfo applicationInfo) {
        this.replaceApplicationApplySetting(applicationInfo, false);
    }

    /**
     * 替换提交设置信息
     *
     * @param applicationInfo applicationInfo
     * @param isPublish       isPublish
     */
    private void replaceApplicationApplySetting(ApplicationInfo applicationInfo, boolean isPublish) {
        // 发布版
        int releaseVersion = ApplicationVersionEnum.RELEASE_VERSION.getId();
        // 设计版
        int designVersion = ApplicationVersionEnum.DESIGN_VERSION.getId();
        ApplicationApplySetting releaseApplySetting = this.baseMapper.findByIdAppIdAndVersion(applicationInfo.getApplicationId(), releaseVersion);
        ApplicationApplySetting designApplySetting = this.baseMapper.findByIdAppIdAndVersion(applicationInfo.getApplicationId(), designVersion);

        if (isPublish) {
            // 发布：设计版 -> 发布版
            this.replaceApplicationApplySetting(designApplySetting, releaseApplySetting);
        } else {
            // 还原：发布版 -> 设计版
            this.replaceApplicationApplySetting(releaseApplySetting, designApplySetting);
        }
    }

    /**
     * 替换提交设置信息
     *
     * @param source source
     * @param target target
     */
    private void replaceApplicationApplySetting(ApplicationApplySetting source, ApplicationApplySetting target) {
        target.setApplyTotalLimitStatus(source.getApplyTotalLimitStatus());
        target.setApplyTotalLimit(source.getApplyTotalLimit());
        target.setApplyMonthLimitStatus(source.getApplyMonthLimitStatus());
        target.setApplyMonthLimit(source.getApplyMonthLimit());
        target.setApplyTimeLimitStatus(source.getApplyTimeLimitStatus());
        target.setApplyLimitBeginTime(source.getApplyLimitBeginTime());
        target.setApplyLimitEndTime(source.getApplyLimitEndTime());

        logService.saveAndCheck(this.baseMapper, ApplicationApplySetting::getApplicationApplySettingId, target);
    }

    /**
     * 创建申请设置
     *
     * @param applicationInfo applicationInfo
     * @param em              em
     * @return ApplicationApplySetting
     */
    private ApplicationApplySetting createApplicationApplySetting(ApplicationInfo applicationInfo, ApplicationVersionEnum em) {
        ApplicationApplySetting applicationApplySetting = new ApplicationApplySetting();
        applicationApplySetting.setEnterpriseId(applicationInfo.getEnterpriseId());
        applicationApplySetting.setApplicationId(applicationInfo.getApplicationId());
        applicationApplySetting.setApplicationVersion(em.getId());
        applicationApplySetting.setApplyTotalLimitStatus(SwitchEnum.NO.getId());
        applicationApplySetting.setApplyMonthLimitStatus(SwitchEnum.NO.getId());
        applicationApplySetting.setApplyTimeLimitStatus(SwitchEnum.NO.getId());
        applicationApplySetting.setIsDeleted(SwitchEnum.NO.getId());

        logService.saveAndCheck(this.baseMapper, ApplicationApplySetting::getApplicationApplySettingId, applicationApplySetting);

        return applicationApplySetting;
    }
}
